﻿using MongoDB.Driver;
using Sustainalytics.ClientDW.DataAccessLayer;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.DataLayer;
using Sustainalytics.DataLayer.Shared;
using Sustainalytics.Entities.ProductInvolvement;
using Sustainalytics.Entities.SustainableProducts;
using Sustainalytics.Portfolios.BL;
using Sustainalytics.ScreeningTool.BL;
using Sustainalytics.Utils;
using Sustainalytics.Utils.Serilog;
using System;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Web.Http;
using System.Web.Http.Cors;

namespace Sustainalytics.ScreeningTool.Service
{
    [EnableCors(origins: "*", headers: "*", methods: "*")]
    //[AutoInvalidateCacheOutput]
    [RoutePrefix("api/v1/export")]
    public class ExportController : ApiController, IExportController
    {
        private readonly ExportScreening _exportScreening;

        public ExportController(
            ICompanyScreeningRepository companyScreeningRepository,
            IClientDwRepository clientDwRepository,
            PortfolioReadHandler portfolioReadHandler,
            IUniversesRepository universesRepository,
            IFilterCriteriaRepository filterCriteriaRepository,
            IScreeningDataRepository screeningDataRepository,
            IRepositoryCollection<CorporateData> corporateDataRepositoryCollection,
            IMongoCollection<CorporateData> corporateDataCollection,
            IMongoCollection<SustainableProductsFramework> sustainableProductFramework,
            IMongoCollection<ProductInvolvementFramework> productInvolvementFramework
            )
        {
            try
            {
                _exportScreening = new ExportScreening(
                    companyScreeningRepository,
                    clientDwRepository,
                    portfolioReadHandler,
                    universesRepository,
                    filterCriteriaRepository,
                    corporateDataRepositoryCollection,
                    screeningDataRepository,
                    corporateDataCollection,
                    sustainableProductFramework,
                    productInvolvementFramework);
            }
            catch (Exception ex)
            {
                throw new HttpResponseException(HttpStatusCode.InternalServerError);
            }
        }

        [Route("")]
        public HttpResponseMessage Post([FromBody] string filterId)
        {
            try
            {
                var userName = this.GetCurrentUserClaims() as ClaimsPrincipal;

                if (filterId == null)
                {
                    return Request.CreateResponse(HttpStatusCode.BadRequest, 
                        new {
                            ErrorStatusCode = ScreeningToolErrorCodesEnum.ExportScreeningInvalidExtraDetails,
                            Message = "Extra details cannot be null!"
                        });
                }
                else
                {

                    byte[] file = _exportScreening.RunScreeningExport(filterId, userName);

                    HttpResponseMessage result = Request.CreateResponse(HttpStatusCode.OK);

                    var strContent = new PushStreamContent((outStream, httpContent, contex) =>
                         {
                             outStream.WriteAsync(file, 0, file.Length);
                             outStream.Close();
                         });

                    strContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
                    strContent.Headers.Add("Content-Disposition", "attachement; filename=" + Guid.NewGuid().ToString() + "_ScreeningTool_" + DateTime.Now.ToString("ddMMyyyy"));
    
                    result.Content = strContent;

                    return result;
                }
            }
            catch (Exception ex)
            {
                return this.Request.CreateResponse(HttpStatusCode.InternalServerError, new { Error = ex.ToString() });
            }
            finally
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();
            }
        }

        [Route("")]
        public HttpResponseMessage Get()
        {
            try
            {
                var userName = this.GetCurrentUserClaims() as ClaimsPrincipal;
                HttpResponseMessage result = Request.CreateResponse(HttpStatusCode.OK, _exportScreening.GetProgressStatus());

                return result;
            }
            catch (Exception ex)
            {
                return this.Request.CreateResponse(HttpStatusCode.InternalServerError, new { Error = ex.ToString() });
            }
        }
    }
}
